import Web3 from "web3";
import { useEffect, useState } from "react";

const EthERC20 = () => {
  const web3 = new Web3("ws://127.0.0.1:7545");

  // === 用户信息 ===
  const [userAddress, setUserAddress] = useState(
    "0xBCaF8506feA8C4BdCDfFA779380af367AfDD2b89"
  );
  const [privateKey, setPrivateKey] = useState(
    "0x296eb70e1aed320aae5d357b0ecbcb4ed28ed4728668b952b2da01fc3c448c6e"
  );

  // ====== 合约数据 =======
  const contractAddressUSDT = "0xA1E0a43Cf4076dA74E86F2fF993115fD35819ae0";
  const contractAbiUSDT = [
    { type: "constructor", inputs: [], stateMutability: "nonpayable" },
    { type: "receive", stateMutability: "payable" },
    {
      type: "function",
      name: "allowance",
      inputs: [
        { name: "", type: "address", internalType: "address" },
        { name: "", type: "address", internalType: "address" }
      ],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "approve",
      inputs: [
        { name: "spender", type: "address", internalType: "address" },
        { name: "value", type: "uint256", internalType: "uint256" }
      ],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "nonpayable"
    },
    {
      type: "function",
      name: "balanceOf",
      inputs: [{ name: "", type: "address", internalType: "address" }],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "buyToken",
      inputs: [],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "payable"
    },
    {
      type: "function",
      name: "decimals",
      inputs: [],
      outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "logArrData",
      inputs: [
        { name: "to", type: "address", internalType: "address" },
        { name: "value", type: "uint256", internalType: "uint256" }
      ],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "nonpayable"
    },
    {
      type: "function",
      name: "name",
      inputs: [],
      outputs: [{ name: "", type: "string", internalType: "string" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "owner",
      inputs: [],
      outputs: [{ name: "", type: "address", internalType: "address" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "queryContractUSDTBalance",
      inputs: [],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "queryUserUSDTMoney",
      inputs: [],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "rate",
      inputs: [],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "symbol",
      inputs: [],
      outputs: [{ name: "", type: "string", internalType: "string" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "totalSupply",
      inputs: [],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "transfer",
      inputs: [
        { name: "to", type: "address", internalType: "address" },
        { name: "value", type: "uint256", internalType: "uint256" }
      ],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "nonpayable"
    },
    {
      type: "function",
      name: "transferFrom",
      inputs: [
        { name: "form", type: "address", internalType: "address" },
        { name: "to", type: "address", internalType: "address" },
        { name: "value", type: "uint256", internalType: "uint256" }
      ],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "nonpayable"
    },
    {
      type: "function",
      name: "withdraw",
      inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
      outputs: [],
      stateMutability: "nonpayable"
    },
    {
      type: "event",
      name: "Approval",
      inputs: [
        {
          name: "owner",
          type: "address",
          indexed: true,
          internalType: "address"
        },
        {
          name: "spender",
          type: "address",
          indexed: true,
          internalType: "address"
        },
        {
          name: "value",
          type: "uint256",
          indexed: false,
          internalType: "uint256"
        }
      ],
      anonymous: false
    },
    {
      type: "event",
      name: "DebugInfo",
      inputs: [
        {
          name: "message",
          type: "string",
          indexed: false,
          internalType: "string"
        },
        {
          name: "before",
          type: "uint256",
          indexed: false,
          internalType: "uint256"
        },
        {
          name: "after1",
          type: "uint256",
          indexed: false,
          internalType: "uint256"
        }
      ],
      anonymous: false
    },
    {
      type: "event",
      name: "DebugInfoAddress",
      inputs: [
        {
          name: "to",
          type: "address",
          indexed: false,
          internalType: "address"
        }
      ],
      anonymous: false
    },
    {
      type: "event",
      name: "Transfer",
      inputs: [
        {
          name: "from",
          type: "address",
          indexed: true,
          internalType: "address"
        },
        {
          name: "to",
          type: "address",
          indexed: true,
          internalType: "address"
        },
        {
          name: "value",
          type: "uint256",
          indexed: false,
          internalType: "uint256"
        }
      ],
      anonymous: false
    }
  ];
  const contractAddressWOW = "0xD6Bd3BeA6263023B496766eb02d67F89c4dDcCe9";
  const contractAbiWOW = [
    {
      type: "constructor",
      inputs: [
        {
          name: "_targetTokenAddress",
          type: "address",
          internalType: "address"
        },
        {
          name: "_exchangeRate",
          type: "uint256",
          internalType: "uint256"
        }
      ],
      stateMutability: "nonpayable"
    },
    { type: "receive", stateMutability: "payable" },
    {
      type: "function",
      name: "allowance",
      inputs: [
        { name: "", type: "address", internalType: "address" },
        { name: "", type: "address", internalType: "address" }
      ],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "approve",
      inputs: [
        { name: "spender", type: "address", internalType: "address" },
        { name: "value", type: "uint256", internalType: "uint256" }
      ],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "nonpayable"
    },
    {
      type: "function",
      name: "balanceOf",
      inputs: [{ name: "", type: "address", internalType: "address" }],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "buyToken",
      inputs: [],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "payable"
    },
    {
      type: "function",
      name: "decimals",
      inputs: [],
      outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "exchangeRate",
      inputs: [],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "exchangeToken",
      inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "nonpayable"
    },
    {
      type: "function",
      name: "name",
      inputs: [],
      outputs: [{ name: "", type: "string", internalType: "string" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "owner",
      inputs: [],
      outputs: [{ name: "", type: "address", internalType: "address" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "queryContractWOWBalance",
      inputs: [],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "queryUserWOWMoney",
      inputs: [],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "rate",
      inputs: [],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "symbol",
      inputs: [],
      outputs: [{ name: "", type: "string", internalType: "string" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "targetTokenAddress",
      inputs: [],
      outputs: [{ name: "", type: "address", internalType: "address" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "totalSupply",
      inputs: [],
      outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
      stateMutability: "view"
    },
    {
      type: "function",
      name: "transfer",
      inputs: [
        { name: "to", type: "address", internalType: "address" },
        { name: "value", type: "uint256", internalType: "uint256" }
      ],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "nonpayable"
    },
    {
      type: "function",
      name: "transferFrom",
      inputs: [
        { name: "from", type: "address", internalType: "address" },
        { name: "to", type: "address", internalType: "address" },
        { name: "value", type: "uint256", internalType: "uint256" }
      ],
      outputs: [{ name: "success", type: "bool", internalType: "bool" }],
      stateMutability: "nonpayable"
    },
    {
      type: "function",
      name: "withdraw",
      inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
      outputs: [],
      stateMutability: "nonpayable"
    },
    {
      type: "event",
      name: "Approval",
      inputs: [
        {
          name: "owner",
          type: "address",
          indexed: true,
          internalType: "address"
        },
        {
          name: "spender",
          type: "address",
          indexed: true,
          internalType: "address"
        },
        {
          name: "value",
          type: "uint256",
          indexed: false,
          internalType: "uint256"
        }
      ],
      anonymous: false
    },
    {
      type: "event",
      name: "DebugInfo",
      inputs: [
        {
          name: "message",
          type: "string",
          indexed: false,
          internalType: "string"
        },
        {
          name: "before",
          type: "uint256",
          indexed: false,
          internalType: "uint256"
        },
        {
          name: "after1",
          type: "uint256",
          indexed: false,
          internalType: "uint256"
        }
      ],
      anonymous: false
    },
    {
      type: "event",
      name: "Transfer",
      inputs: [
        {
          name: "from",
          type: "address",
          indexed: true,
          internalType: "address"
        },
        {
          name: "to",
          type: "address",
          indexed: true,
          internalType: "address"
        },
        {
          name: "value",
          type: "uint256",
          indexed: false,
          internalType: "uint256"
        }
      ],
      anonymous: false
    }
  ];

  // 创建合约对象
  const contractUSDT = new web3.eth.Contract(
    contractAbiUSDT,
    contractAddressUSDT
  );

  const contractWOW = new web3.eth.Contract(contractAbiWOW, contractAddressWOW);

  // === 资产信息 ===
  const [contractETH, setContractETH] = useState("0");
  const [wowAllMoney, setWowAllMoney] = useState("0");
  const [USDTAllMoney, setUSDTAllMoney] = useState("0");

  const [userETHMoney, setUserETHMoney] = useState("0");
  const [userWOWMoney, setUserWOWMoney] = useState("0");
  const [userUSDTMoney, setUserUSDTMoney] = useState("0");

  const [exETHNum, setExETHNum] = useState("");
  const [exETHUSDT, setExETHUSDT] = useState("");
  const [WOWExchangeUSDTNum, setWOWExchangeUSDTNum] = useState("");

  useEffect(() => {
    web3.eth.net
      .isListening()
      .then((res) => {
        console.log("is ok =>", res);
        queryContractETH();
        queryUSDTAllMoney();
        queryUserETHMoney();
        queryWowAllMoney();
        queryUserWOWMoney();
        queryUserUSDTMoney();
      })
      .catch((err) => {
        console.log("no create err =>", err);
      });
  }, []); // 空依赖数组，确保只执行一次

  // 查询合同 ETH
  const queryContractETH = async () => {
    try {
      const balance = await web3.eth.getBalance(contractAddressWOW);
      setContractETH(`${web3.utils.fromWei(balance, "ether")} ether`);
    } catch (err) {
      console.log("queryWowAllMoney =>", err);
    }
  };

  // 查询 wow 所有资产
  const queryWowAllMoney = async () => {
    try {
      const balance = await contractWOW.methods
        .queryContractWOWBalance()
        .call();
      setWowAllMoney(`${web3.utils.fromWei(balance, "ether")} WOW`);
    } catch (err) {
      console.log("queryWowAllMoney =>", err);
    }
  };

  // 查询 USDT 所有资产
  const queryUSDTAllMoney = async () => {
    try {
      const balance = await contractUSDT.methods
        .queryContractUSDTBalance()
        .call();
      setUSDTAllMoney(`${web3.utils.fromWei(balance, "ether")} USDT`);
    } catch (err) {
      console.log("queryMoney =>", err);
    }
  };

  // 查询用户 ETH 资产
  const queryUserETHMoney = async () => {
    if (userAddress === "") return;
    try {
      const balance = await web3.eth.getBalance(userAddress);
      setUserETHMoney(`${web3.utils.fromWei(balance, "ether")} ether`);
    } catch (err) {
      console.log("queryMoney =>", err);
    }
  };

  // 查询用户 wow 资产
  const queryUserWOWMoney = async () => {
    if (userAddress === "") return;
    try {
      const balance = await contractWOW.methods
        .queryUserWOWMoney()
        .call({ from: userAddress });
      setUserWOWMoney(`${web3.utils.fromWei(balance, "ether")} WOW`);
    } catch (err) {
      console.log("queryMoney =>", err);
    }
  };

  // 查询用户 USDT 资产
  const queryUserUSDTMoney = async () => {
    if (userAddress === "") return;
    try {
      const balance = await contractUSDT.methods
        .queryUserUSDTMoney()
        .call({ from: userAddress });
      setUserUSDTMoney(`${web3.utils.fromWei(balance, "ether")} USDT`);
    } catch (err) {
      console.log("queryMoney =>", err);
    }
  };

  // eth exchange wow
  const EthExWowBtn = async () => {
    if (userAddress === "" || exETHNum === "") return;
    const tx = {
      from: userAddress,
      to: contractAddressWOW,
      value: web3.utils.toWei(exETHNum, "ether")
    };
    web3.eth.sendTransaction(tx, (err, hash) => {
      if (err) {
        console.log("err =>", err);
      } else {
        console.log("hash =>", hash);
      }
    });
  };

  // eth exchange USDT
  const EthExUSDTBtn = async () => {
    if (userAddress === "" || exETHUSDT === "") return;
    const tx = {
      from: userAddress,
      to: contractAddressUSDT,
      value: web3.utils.toWei(exETHUSDT, "ether")
    };
    web3.eth.sendTransaction(tx, (err, hash) => {
      if (err) {
        console.log("err =>", err);
      } else {
        console.log("hash =>", hash);
      }
    });
  };

  // wow exchange usdt
  const WOWExchangeUSDTBtn = async () => {
    if (userAddress === "" || WOWExchangeUSDTNum === "") return;
    // 获取用户的nonce
    const gasPrice = await web3.eth.getGasPrice(); // 2.1 获取当前网络的 gas 价格

    const tx_data = contractWOW.methods
      .exchangeToken(web3.utils.toWei(WOWExchangeUSDTNum, "ether"))
      .encodeABI();

    const tx = {
      from: userAddress,
      to: contractAddressWOW,
      gas: 2000000, // 设置适当的gas限制
      data: tx_data,
      gasPrice
    };

    // 使用私钥对交易进行签名
    const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey);

    // 发送签名后的交易
    web3.eth
      .sendSignedTransaction(signedTx.rawTransaction)
      .on("receipt", (receipt) => {
        console.log("Transaction receipt:", receipt);
      })
      .on("error", (error) => {
        console.error("Error:", error);
      });
  };

  // 历史记录
  const EthHistoryList = async () => {
    // const resTransfer = await contractWOW.events.Transfer({
    //   fromBlock: "latest"
    // });
    // resTransfer.on("data", (event) => {
    //   console.log("WOW Transfer =>", event);
    // });
    // resTransfer.on("error", (event) => {
    //   console.log("WOW Transfer Error =>", event);
    // });

    const resDebugInfo = await contractWOW.events.DebugInfo({
      fromBlock: 0
    });
    resDebugInfo.on("data", (event) => {
      console.log("WOW Transfer =>", event);
    });
    resDebugInfo.on("error", (event) => {
      console.log("WOW Transfer Error =>", event);
    });
  };

  useEffect(() => {
    EthHistoryList();
  }, []);

  return (
    <div>
      <p>WOW Contract ETH:{contractETH}</p>
      <p>WOW ALl Money: {wowAllMoney}</p>
      <p>USDT ALl Money: {USDTAllMoney}</p>
      <p>userETHMoney:{userETHMoney}</p>
      <p>userWOWMoney:{userWOWMoney}</p>
      <p>userUSDTMoney:{userUSDTMoney}</p>

      <div className="pd-5">
        <p>ETH Exchange WOW</p>
        <input
          type="number"
          value={exETHNum}
          onChange={(e) => setExETHNum(e.target.value)}
        />
        <button type="button" onClick={EthExWowBtn}>
          go1
        </button>
      </div>

      <div className="pd-5">
        <p>ETH Exchange USDT</p>
        <input
          type="number"
          value={exETHUSDT}
          onChange={(e) => setExETHUSDT(e.target.value)}
        />
        <button type="button" onClick={EthExUSDTBtn}>
          go2
        </button>
      </div>

      <div className="pd-5">
        <p>WOW Exchange USDT</p>
        <input
          type="number"
          value={WOWExchangeUSDTNum}
          onChange={(e) => setWOWExchangeUSDTNum(e.target.value)}
        />
        <button type="button" onClick={WOWExchangeUSDTBtn}>
          go3
        </button>
      </div>
    </div>
  );
};

export default EthERC20;
